import { speechRecognizer } from '@kit.CoreSpeechKit';
import { BusinessError } from '@kit.BasicServicesKit';
import AudioCapturer from './AudioCapturer';

// 接口定义应在调用它的地方，所以我们从 Index.ets 中获取 AsrListener 的定义
// 但为避免循环依赖，我们在此处重新定义它，或确保它在一个公共文件中
interface AsrListener {
  onStart: () => void;
  onResult: (id: string, res: { isFinal: boolean; result: string; }) => void;
  onComplete: () => void;
  onError: (id: string, code: number, msg: string) => void;
  onEvent: (sessionId: string, eventCode: number, eventMessage: string) => void;
}

// 为底层引擎的监听器定义一个明确的接口
interface EngineListener {
    onStart: (sessionId: string) => void;
    onResult: (sessionId: string, res: {isFinal: boolean, result: string}) => void;
    onComplete: (sessionId: string) => void;
    onError: (sessionId: string, code: number, msg: string) => void;
    onEvent: (sessionId: string, eventCode: number, eventMessage: string) => void;
}

let asrEngine: speechRecognizer.SpeechRecognitionEngine;

export class AsrService {
  private audioCapturer: AudioCapturer = new AudioCapturer();
  private listener: AsrListener; // 使用明确的接口类型
  private sessionId: string;
  private isInitialized: boolean = false;

  constructor(listener: AsrListener) { // 使用明确的接口类型
    this.listener = listener;
  }

  public init(): Promise<void> {
    return new Promise((resolve, reject) => {
      if (this.isInitialized) {
        return resolve();
      }
      console.info('AsrService: Creating engine...');
      const initParams: speechRecognizer.CreateEngineParams = { language: 'zh-CN', online: 1 };
      try {
        speechRecognizer.createEngine(initParams, (err, engine) => {
          if (err) {
            console.error(`AsrService: Failed to create engine, code: ${err.code}, message: ${err.message}`);
            this.listener.onError?.("init", err.code, err.message);
            return reject(err);
          }
          console.info('AsrService: Engine created successfully.');
          asrEngine = engine;
          
          // 创建一个符合 speechRecognizer.RecognitionListener 签名的包装器
          const engineListener: EngineListener = {
              onStart: (sessionId: string) => this.listener.onStart(),
              onResult: (sessionId: string, res: {isFinal: boolean, result: string}) => this.listener.onResult(sessionId, res),
              onComplete: (sessionId: string) => this.listener.onComplete(),
              onError: (sessionId: string, code: number, msg: string) => this.listener.onError(sessionId, code, msg),
              onEvent: (sessionId: string, eventCode: number, eventMessage: string) => this.listener.onEvent(sessionId, eventCode, eventMessage)
          };
          
          asrEngine.setListener(engineListener as speechRecognizer.RecognitionListener);
          this.isInitialized = true;
          resolve();
        });
      } catch (e) {
        const error = e as BusinessError;
        console.error(`AsrService: createEngine error: ${error.message}`);
        this.listener.onError?.("init", error.code, error.message);
        reject(error);
      }
    });
  }

  public async start() {
    if (!this.isInitialized || !asrEngine) {
      console.error('AsrService: Engine not ready, cannot start.');
      this.listener.onError?.("start", -1, "Engine not initialized");
      return;
    }
    console.info('AsrService: Starting listening and recording.');
    this.sessionId = `session_${Date.now()}`;
    const startParams: speechRecognizer.StartParams = {
      sessionId: this.sessionId,
      audioInfo: { audioType: 'pcm', sampleRate: 16000, soundChannel: 1, sampleBit: 16 },
      extraParams: { "vadEnd": 3000 }
    };
    asrEngine.startListening(startParams);
    await this.startRecording();
  }

  private async startRecording() {
    try {
      await this.audioCapturer.init((dataBuffer) => {
        if (asrEngine && this.sessionId) {
          asrEngine.writeAudio(this.sessionId, new Uint8Array(dataBuffer));
        }
      });
      await this.audioCapturer.start();
    } catch (error) {
      console.error('AsrService: Failed to start recording', error);
      this.listener.onError?.("recording", -1, "Failed to start recording");
    }
  }

  public stop() {
    console.info('AsrService: Stopping listening and recording.');
    this.audioCapturer.stop();
    if (asrEngine && this.sessionId) {
      asrEngine.finish(this.sessionId);
    }
  }

  public shutdown() {
    console.info('AsrService: Shutting down engine.');
    this.audioCapturer.release();
    if (asrEngine) {
      asrEngine.shutdown();
    }
  }
} 